#!/bin/sh
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# TODO(josephsih): need to have some way to derive this list
# from system attributes automatically.
DEVICES_WITHOUT_BUILT_IN_TOUCHPAD="stumpy"

set_pref_vars() {
  local name=$1
  PREF_FILE=$(eval echo \$PREF_${name}_FILE)
  PREF_VALID=$(eval echo \$PREF_${name}_VALID)
  PREF_DEFAULT=$(eval echo \$PREF_${name}_DEFAULT)
}

load_pref() {
  local name="$1"
  set_pref_vars "$name"
  local file_size="$(stat -c %s $PREF_FILE)"
  if [ "$file_size" != "2" ]; then
    # invalid file size
    echo "$PREF_DEFAULT"
    return
  fi
  local value="$(cat "$PREF_FILE")"
  case $value in
    $PREF_VALID) echo "$value";;
    *) echo "$PREF_DEFAULT";;
  esac
}

store_pref() {
  local name="$1"
  local value="$2"
  set_pref_vars "$name"
  case $value in
    $PREF_VALID) ;;
    *) return;;
  esac
  echo $value > "$PREF_FILE"
}

list_input_device() {
  xinput --list --id-only
}

get_device_name() {
  if [ -z "$1" ]; then
    return 1
  fi
  xinput --list --name-only $1
}

canonical_ids() {
  # In case minus number is passed, truncate it to the last 4 hexdigits.
  # e.g., -16360 -> ffffffffffffc018 -> c018
  local id_strings id_str first
  read id_strings
  for id_str in $id_strings; do
    if [ -n "$first" ]; then
      printf ":"
    fi
    printf "%04x" "$id_str" | sed 's/.*\(.\{4\}\)$/\1/'
    first="not"
  done
}

vendor_product_for_xinput_id() {
  local xinput_id="$1"

  local vp="$(xinput list-props $xinput_id 2>/dev/null \
              | fgrep "Device Product ID" | \
              cut -d : -f 2 | sed 's/,//' | canonical_ids)"
  if ! echo "${vp}" | grep -q ':'; then
    vp="$(xinput list-props $xinput_id 2>/dev/null \
          | fgrep "Device Vendor ID" | \
          cut -d : -f 2 | canonical_ids)"
    vp="${vp}:$(xinput list-props $xinput_id 2>/dev/null \
          | fgrep "Device Product ID" | \
          cut -d : -f 2 | canonical_ids)"
  fi
  echo "$vp"
}

is_multitouch_mouse() {
  # Whitelist of multitouch mice.
  case "$(vendor_product_for_xinput_id $1)" in
    "05ac:030d") true;;  # Apple magicmouse (BT)
    "046d:4026") true;;  # Logitech T400 (Unifying)
    "046d:4027") true;;  # Logitech T620 (Unifying)
    "046d:b00d") true;;  # Logitech Touch Mouse (BT)
    *)           false;;
  esac
}

find_pad() {
  # Print the ID for any device that uses out touchpad driver,
  # including touch mice. We do this by looking for a magic
  # property.
  local device_id
  for device_id in $(list_input_device); do
    if $XINPUT list-props ${device_id} 2>/dev/null | \
        grep -q '^[[:blank:]]Integrated Touchpad (' ; then
      echo ${device_id}
    elif is_multitouch_mouse ${device_id}; then
      echo ${device_id}
    fi
  done
}

find_touchscreen() {
  # Use xinput to find if any touchscreen device is present. Then find its
  # device ID number.
  local device_id
  for device_id in $(list_input_device); do
    if get_device_name ${device_id} | grep -q '[tT]ouch[sS]creen'; then
      echo ${device_id}
    fi
  done
}

# Returns the xinput ID of the newly attached mouse. If X hasn't loaded a driver
# for the new mouse, yet, this will not print anything. If found, it prints the
# xinput ID. The env var DEVNAME must be set (as it is by udev).
get_added_xinput_id() {
  # Must have $DEVNAME set
  if [ -z "$DEVNAME" ]; then
    return
  fi
  # Get the list of xinput IDs:
  local ids="$($XINPUT list | sed 's/.*id=\([0-9]*\).*/\1/g')"
  if [ -z "$ids" ]; then
    return
  fi
  for id in $ids; do
    local test_node=$($XINPUT list-props $id | grep "Device Node" | \
                      cut -d '"' -f 2)
    if [ "$test_node" = "$DEVNAME" ]; then
      echo $id
      return
    fi
  done
}

wait_and_get_added_xinput_id() {
  tries=10
  while [ "$tries" -ne "0" ]; do
    tries=$((tries - 1))
    newid=$(get_added_xinput_id)
    if [ -n "$newid" ]; then
      break
    fi
    sleep 1
  done
  echo $newid
}
